﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Types
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ColorPixel<T>
    {
        private Color m_Color = Color.Transparent;
        private T m_Value = default(T);
        private Point m_Point = new Point(-1,-1);

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorPixel&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="_color">The _color.</param>
        /// <param name="_value">The _value.</param>
        public ColorPixel(Color _color, T _value)
            : this(_color, new Point(-1, -1), _value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorPixel&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="_color">The _color.</param>
        /// <param name="_ptPoint">The _PT point.</param>
        /// <param name="_value">The _value.</param>
        public ColorPixel(Color _color, Point _ptPoint, T _value)
        {
            m_Color = _color;
            m_Value = _value;
            m_Point = _ptPoint;
        }

        /// <summary>
        /// Gets or sets the color.
        /// </summary>
        /// <value>The color.</value>
        public Color Color
        {
            get { return m_Color; }
            set { m_Color = value; }
        }

        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        /// <value>The value.</value>
        public T Value
        {
            get { return (T)m_Value; }
            set { m_Value = value; }
        }

        /// <summary>
        /// Gets or sets the point.
        /// </summary>
        /// <value>The point.</value>
        public Point Point
        {
            get { return m_Point; }
            set { m_Point = value; }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ColorPixelList<T> : List<ColorPixel<T>>
    {
        public ColorPixelList()
        {
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ColorPixelSorter<T> : IComparer<ColorPixel<T>>
    {
        #region IComparer<ColorPixel<int>> Member

        private PROCESSING_MODE m_ColorPixelSortMode = PROCESSING_MODE.None;

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorPixelSorter&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="_sortMode">The _sort mode.</param>
        public ColorPixelSorter(PROCESSING_MODE _sortMode)
        {
            this.m_ColorPixelSortMode = _sortMode;
        }

        /// <summary>
        /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
        /// </summary>
        /// <param name="x">The first object to compare.</param>
        /// <param name="y">The second object to compare.</param>
        /// <returns>
        /// Value
        /// Condition
        /// Less than zero
        /// <paramref name="x"/> is less than <paramref name="y"/>.
        /// Zero
        /// <paramref name="x"/> equals <paramref name="y"/>.
        /// Greater than zero
        /// <paramref name="x"/> is greater than <paramref name="y"/>.
        /// </returns>
        public int Compare(ColorPixel<T> x, ColorPixel<T> y)
        {
            int nResult = -2;

            switch (m_ColorPixelSortMode)
            {
                case PROCESSING_MODE.A:
                    nResult = x.Color.A.CompareTo(y.Color.A);
                    break;

                case PROCESSING_MODE.R:
                    nResult = x.Color.R.CompareTo(y.Color.R);
                    break;

                case PROCESSING_MODE.G:
                    nResult = x.Color.G.CompareTo(y.Color.G);
                    break;

                case PROCESSING_MODE.B:
                    nResult = x.Color.B.CompareTo(y.Color.B);
                    break;

                case PROCESSING_MODE.Brightness:
                    nResult = x.Color.GetBrightness().CompareTo(y.Color.GetBrightness());
                    break;

                case PROCESSING_MODE.Color:
                    nResult = x.Color.ToArgb().CompareTo(y.Color.ToArgb());
                    break;

                case PROCESSING_MODE.ColorConstancy:
                    throw new InvalidOperationException();
                    break;

                case PROCESSING_MODE.ColorCount:
                    throw new InvalidOperationException();
                    break;

                case PROCESSING_MODE.GrayColor:
                    nResult = ColorFunctions.Gray(x.Color).CompareTo(ColorFunctions.Gray(y.Color));
                    break;

                case PROCESSING_MODE.Hue:
                    nResult = x.Color.GetHue().CompareTo(y.Color.GetHue());
                    break;

                case PROCESSING_MODE.Luminance:
                    nResult = ColorFunctions.GetLuminance(x.Color).CompareTo(ColorFunctions.GetLuminance(y.Color));
                    break;

                case PROCESSING_MODE.MulARGB:
                    nResult = (x.Color.A * x.Color.R * x.Color.G * x.Color.G).CompareTo(y.Color.A * y.Color.R * y.Color.G * y.Color.B);
                    break;

                case PROCESSING_MODE.MulRGB:
                    nResult = (x.Color.R * x.Color.G * x.Color.G).CompareTo(y.Color.R * y.Color.G * y.Color.B);
                    break;

                case PROCESSING_MODE.Saturation:
                    nResult = x.Color.GetSaturation().CompareTo(y.Color.GetSaturation());
                    break;

                case PROCESSING_MODE.SumARGB:
                    nResult = (x.Color.A + x.Color.R + x.Color.G + x.Color.B).CompareTo(y.Color.A + y.Color.R + y.Color.G + y.Color.B);
                    break;

                case PROCESSING_MODE.SumRGB:
                    nResult = (x.Color.R + x.Color.G + x.Color.B).CompareTo(y.Color.R + y.Color.G + y.Color.B);
                    break;
            }
            return nResult;
        }

        #endregion
    }
}
